package com.example.demo.util;

import com.example.demo.entity.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.annotation.Resource;
import java.util.Date;


public class JwtUtil {
    private static final String SECRET_KEY = "pet-management-system"; // 生成和验证 Token 时使用的密钥

    /*
    TODO
    还差引入Mapper，通过userName进行用户信息查询的方法
     */

    // 设置过期时间
    private static final long EXPIRATION_TIME = 2000L * 1000 * 60 * 60; // 1小时，你实际的过期时间是200小时，基本上token不会失效


    // 生成会员专用的 JWT Token
    public static String generateMemberToken(User user) {
        return Jwts.builder().setSubject(user.getUsername())  // 设置用户ID作为主题
                .claim("id", user.getId())  // 添加用户名
                .claim("username", user.getUsername())  // 添加用户名
                .claim("fullName", user.getFullName())  // 添加全名
                .claim("password", user.getPassword())  // 添加密码
                .claim("idCardNo", user.getIdCardNo())  // 添加身份证号
                .claim("phone", user.getPhone())  // 添加手机号
                .claim("gender", user.getGender())  // 添加性别
                .claim("age", user.getAge())  // 添加年龄
                .claim("address", user.getAddress())  // 添加地址
                .claim("avatar", user.getAvatar())  // 添加地址
                .setIssuedAt(new Date())  // 设置生成时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))  // 设置过期时间
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)  // 签名
                .compact();
    }
//看一下这一段，可记得，最早的时候我远程写的，这里面的字段就是你用户表里的字段，直接是把用户信息返回以后组装成一条内容然后生成token的

    // 生成 JWT Token
    public static String generateToken(String username) {
        return Jwts.builder().setSubject(username)  // 设置用户信息
                .setIssuedAt(new Date())  // 设置生成时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))  // 设置过期时间
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)  // 签名
                .compact();
    }

    // 从 Token 中获取用户名
    public static String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
        return claims.getSubject();
    }

    // 验证 Token 是否有效
    public static boolean isTokenExpired(String token) {
        try {
            // 解析 token 获取过期时间
            Date expiration = Jwts.parser()
                    .setSigningKey(SECRET_KEY) // 使用密钥解析
                    .parseClaimsJws(token)     // 解析 JWT
                    .getBody()                 // 获取 body
                    .getExpiration();          // 获取过期时间

            // 比较过期时间与当前时间
            return expiration.before(new Date()); // 如果过期时间在当前时间之前，则表示 token 已经过期
        } catch (JwtException e) {
            // 捕获 JWT 解析异常（例如 token 无效）
            return true;
        }
    }

    // 验证 Token 是否有效
    public static boolean validateToken(String token, String username) {
        String usernameFromToken = getUsernameFromToken(token);
        return usernameFromToken.equals(username) && !isTokenExpired(token);
    }

    // 让 Token 失效
    public static String invalidateToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();

        // 设置 Token 的过期时间为过去的时间（例如：1分钟前）
        long now = System.currentTimeMillis();
        claims.setExpiration(new Date(now - 60000));

        // 重新构建 Token
        return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, SECRET_KEY).compact();
    }

    // 通过 Token 解析 User 对象
    public static User getUserFromToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
        User user = new User();
        user.setId(claims.get("id", Long.class));
        user.setUsername(claims.getSubject());
        user.setFullName(claims.get("fullName", String.class));
        user.setPassword(claims.get("password", String.class));
        user.setIdCardNo(claims.get("idCardNo", String.class));
        user.setPhone(claims.get("phone", String.class));
        user.setGender(claims.get("gender", Integer.class));
        user.setAge(claims.get("age", Integer.class));
        user.setAddress(claims.get("address", String.class));
        return user;
    }
}